home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / program / ixemlsrc.lha / ixemul / network / res_query.c < prev    next >
C/C++ Source or Header  |  1995-12-23  |  8KB  |  282 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)res_query.c    5.11 (Berkeley) 3/6/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <netinet/in.h>
  40. #include <arpa/inet.h>
  41. #include <arpa/nameser.h>
  42. #include <netdb.h>
  43. #include <resolv.h>
  44. #include <stdio.h>
  45. #include <ctype.h>
  46. #include <errno.h>
  47. #include <stdlib.h>
  48. #include <string.h>
  49.  
  50. #if PACKETSZ > 1024
  51. #define MAXPACKET    PACKETSZ
  52. #else
  53. #define MAXPACKET    1024
  54. #endif
  55.  
  56. int h_errno;
  57.  
  58. /*
  59.  * Formulate a normal query, send, and await answer.
  60.  * Returned answer is placed in supplied buffer "answer".
  61.  * Perform preliminary check of answer, returning success only
  62.  * if no error is indicated and the answer count is nonzero.
  63.  * Return the size of the response on success, -1 on error.
  64.  * Error number is left in h_errno.
  65.  * Caller must parse answer and determine whether it answers the question.
  66.  */
  67. res_query(name, class, type, answer, anslen)
  68.     char *name;        /* domain name */
  69.     int class, type;    /* class and type of query */
  70.     u_char *answer;        /* buffer to put answer */
  71.     int anslen;        /* size of answer buffer */
  72. {
  73.     char buf[MAXPACKET];
  74.     HEADER *hp;
  75.     int n;
  76.  
  77.     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  78.         return (-1);
  79. #ifdef DEBUG
  80.     if (_res.options & RES_DEBUG)
  81.         printf("res_query(%s, %d, %d)\n", name, class, type);
  82. #endif
  83.     n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL,
  84.         buf, sizeof(buf));
  85.  
  86.     if (n <= 0) {
  87. #ifdef DEBUG
  88.         if (_res.options & RES_DEBUG)
  89.             printf("res_query: mkquery failed\n");
  90. #endif
  91.         h_errno = NO_RECOVERY;
  92.         return (n);
  93.     }
  94.     n = res_send(buf, n, (char *)answer, anslen);
  95.     if (n < 0) {
  96. #ifdef DEBUG
  97.         if (_res.options & RES_DEBUG)
  98.             printf("res_query: send error\n");
  99. #endif
  100.         h_errno = TRY_AGAIN;
  101.         return(n);
  102.     }
  103.  
  104.     hp = (HEADER *) answer;
  105.     if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
  106. #ifdef DEBUG
  107.         if (_res.options & RES_DEBUG)
  108.             printf("rcode = %d, ancount=%d\n", hp->rcode,
  109.                 ntohs(hp->ancount));
  110. #endif
  111.         switch (hp->rcode) {
  112.             case NXDOMAIN:
  113.                 h_errno = HOST_NOT_FOUND;
  114.                 break;
  115.             case SERVFAIL:
  116.                 h_errno = TRY_AGAIN;
  117.                 break;
  118.             case NOERROR:
  119.                 h_errno = NO_DATA;
  120.                 break;
  121.             case FORMERR:
  122.             case NOTIMP:
  123.             case REFUSED:
  124.             default:
  125.                 h_errno = NO_RECOVERY;
  126.                 break;
  127.         }
  128.         return (-1);
  129.     }
  130.     return(n);
  131. }
  132.  
  133. /*
  134.  * Formulate a normal query, send, and retrieve answer in supplied buffer.
  135.  * Return the size of the response on success, -1 on error.
  136.  * If enabled, implement search rules until answer or unrecoverable failure
  137.  * is detected.  Error number is left in h_errno.
  138.  * Only useful for queries in the same name hierarchy as the local host
  139.  * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
  140.  */
  141. res_search(name, class, type, answer, anslen)
  142.     char *name;        /* domain name */
  143.     int class, type;    /* class and type of query */
  144.     u_char *answer;        /* buffer to put answer */
  145.     int anslen;        /* size of answer */
  146. {
  147.     register char *cp, **domain;
  148.     int n, ret, got_nodata = 0;
  149.     char *__hostalias();
  150.  
  151.     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  152.         return (-1);
  153.  
  154.     errno = 0;
  155.     h_errno = HOST_NOT_FOUND;        /* default, if we never query */
  156.     for (cp = name, n = 0; *cp; cp++)
  157.         if (*cp == '.')
  158.             n++;
  159.     if (n == 0 && (cp = __hostalias(name)))
  160.         return (res_query(cp, class, type, answer, anslen));
  161.  
  162.     /*
  163.      * We do at least one level of search if
  164.      *    - there is no dot and RES_DEFNAME is set, or
  165.      *    - there is at least one dot, there is no trailing dot,
  166.      *      and RES_DNSRCH is set.
  167.      */
  168.     if ((n == 0 && _res.options & RES_DEFNAMES) ||
  169.        (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
  170.          for (domain = _res.dnsrch; *domain; domain++) {
  171.         ret = res_querydomain(name, *domain, class, type,
  172.             answer, anslen);
  173.         if (ret > 0)
  174.             return (ret);
  175.         /*
  176.          * If no server present, give up.
  177.          * If name isn't found in this domain,
  178.          * keep trying higher domains in the search list
  179.          * (if that's enabled).
  180.          * On a NO_DATA error, keep trying, otherwise
  181.          * a wildcard entry of another type could keep us
  182.          * from finding this entry higher in the domain.
  183.          * If we get some other error (negative answer or
  184.          * server failure), then stop searching up,
  185.          * but try the input name below in case it's fully-qualified.
  186.          */
  187.         if (errno == ECONNREFUSED) {
  188.             h_errno = TRY_AGAIN;
  189.             return (-1);
  190.         }
  191.         if (h_errno == NO_DATA)
  192.             got_nodata++;
  193.         if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
  194.             (_res.options & RES_DNSRCH) == 0)
  195.             break;
  196.     }
  197.     /*
  198.      * If the search/default failed, try the name as fully-qualified,
  199.      * but only if it contained at least one dot (even trailing).
  200.      * This is purely a heuristic; we assume that any reasonable query
  201.      * about a top-level domain (for servers, SOA, etc) will not use
  202.      * res_search.
  203.      */
  204.     if (n && (ret = res_querydomain(name, (char *)NULL, class, type,
  205.         answer, anslen)) > 0)
  206.         return (ret);
  207.     if (got_nodata)
  208.         h_errno = NO_DATA;
  209.     return (-1);
  210. }
  211.  
  212. /*
  213.  * Perform a call on res_query on the concatenation of name and domain,
  214.  * removing a trailing dot from name if domain is NULL.
  215.  */
  216. res_querydomain(name, domain, class, type, answer, anslen)
  217.     char *name, *domain;
  218.     int class, type;    /* class and type of query */
  219.     u_char *answer;        /* buffer to put answer */
  220.     int anslen;        /* size of answer */
  221. {
  222.     char nbuf[2*MAXDNAME+2];
  223.     char *longname = nbuf;
  224.     int n;
  225.  
  226. #ifdef DEBUG
  227.     if (_res.options & RES_DEBUG)
  228.         printf("res_querydomain(%s, %s, %d, %d)\n",
  229.             name, domain, class, type);
  230. #endif
  231.     if (domain == NULL) {
  232.         /*
  233.          * Check for trailing '.';
  234.          * copy without '.' if present.
  235.          */
  236.         n = strlen(name) - 1;
  237.         if (name[n] == '.' && n < sizeof(nbuf) - 1) {
  238.             bcopy(name, nbuf, n);
  239.             nbuf[n] = '\0';
  240.         } else
  241.             longname = name;
  242.     } else
  243.         (void)sprintf(nbuf, "%.*s.%.*s",
  244.             MAXDNAME, name, MAXDNAME, domain);
  245.  
  246.     return (res_query(longname, class, type, answer, anslen));
  247. }
  248.  
  249. char *
  250. __hostalias(name)
  251.     register const char *name;
  252. {
  253.     register char *C1, *C2;
  254.     FILE *fp;
  255.     char *file, *getenv(), *strcpy(), *strncpy();
  256.     char buf[BUFSIZ];
  257.     static char abuf[MAXDNAME];
  258.  
  259.     file = getenv("HOSTALIASES");
  260.     if (file == NULL || (fp = fopen(file, "r")) == NULL)
  261.         return (NULL);
  262.     buf[sizeof(buf) - 1] = '\0';
  263.     while (fgets(buf, sizeof(buf), fp)) {
  264.         for (C1 = buf; *C1 && !isspace(*C1); ++C1);
  265.         if (!*C1)
  266.             break;
  267.         *C1 = '\0';
  268.         if (!strcasecmp(buf, name)) {
  269.             while (isspace(*++C1));
  270.             if (!*C1)
  271.                 break;
  272.             for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
  273.             abuf[sizeof(abuf) - 1] = *C2 = '\0';
  274.             (void)strncpy(abuf, C1, sizeof(abuf) - 1);
  275.             fclose(fp);
  276.             return (abuf);
  277.         }
  278.     }
  279.     fclose(fp);
  280.     return (NULL);
  281. }
  282.